import { childEnglishApi } from '@/api/childEnglishApi';
import CryptoJS from 'crypto-js';

class FileService {
  constructor() {
    this.uploadQueue = new Map();
    this.downloadQueue = new Map();
    this.maxConcurrentUploads = 3;
    this.maxConcurrentDownloads = 3;
  }

  /**
   * 普通文件上传
   */
  async uploadFile(file, options = {}) {
    const {
      onProgress = null,
      onSuccess = null,
      onError = null,
      fileType = null
    } = options;

    try {
      const response = await childEnglishApi.uploadFile(file, onProgress, fileType);

      if (onSuccess) {
        onSuccess(response);
      }

      return response;
    } catch (error) {
      console.error('文件上传失败:', error);

      if (onError) {
        onError(error);
      }

      throw error;
    }
  }

  /**
   * 大文件分片上传
   */
  async uploadLargeFile(file, options = {}) {
    const {
      chunkSize = 5 * 1024 * 1024, // 5MB
      onProgress = null,
      onChunkProgress = null,
      onChunkComplete = null,
      onSuccess = null,
      onError = null,
      maxRetries = 3
    } = options;

    const fileId = this.generateFileId(file);
    const totalChunks = Math.ceil(file.size / chunkSize);

    // 创建上传任务
    const uploadTask = {
      fileId,
      file,
      chunkSize,
      totalChunks,
      uploadedChunks: 0,
      progress: 0,
      status: 'pending',
      retryCount: 0,
      chunks: {},
      md5: null
    };

    this.uploadQueue.set(fileId, uploadTask);

    try {
      // 1. 计算文件MD5（大文件可以抽样计算）
      uploadTask.md5 = await this.calculateFileMD5(file);

      // 2. 检查分片状态
      const chunkStatus = await childEnglishApi.checkChunkStatus({
        fileMd5: uploadTask.md5,
        fileName: file.name,
        fileSize: file.size,
        chunkSize: chunkSize,
        totalChunks: totalChunks
      });

      // 3. 如果文件已存在，直接返回
      if (chunkStatus.status === 'completed') {
        uploadTask.status = 'completed';
        uploadTask.progress = 100;

        if (onProgress) {
          onProgress(100);
        }

        if (onSuccess) {
          onSuccess(chunkStatus);
        }

        return chunkStatus;
      }

      // 4. 更新已上传的分片信息
      if (chunkStatus.uploadedChunks && chunkStatus.uploadedChunks.length > 0) {
        uploadTask.uploadedChunks = chunkStatus.uploadedChunks.length;
        uploadTask.progress = (uploadTask.uploadedChunks / totalChunks) * 100;

        // 标记已上传的分片
        chunkStatus.uploadedChunks.forEach(chunkNumber => {
          uploadTask.chunks[chunkNumber] = 'completed';
        });
      }

      // 5. 开始上传分片
      await this.uploadChunks(uploadTask, {
        onChunkProgress,
        onChunkComplete,
        onProgress,
        maxRetries
      });

      // 6. 合并分片
      // 获取当前用户信息（只从sessionStorage读取）
      const userData = sessionStorage.getItem('user');
      const user = userData ? JSON.parse(userData) : null;
      const uploadUser = user ? user.username : null;

      // 根据文件扩展名判断文件类型
      const extension = file.name.substring(file.name.lastIndexOf('.') + 1).toLowerCase();
      let fileType = options.fileType || null;
      if (!fileType) {
        if (['pdf', 'ppt', 'pptx', 'doc', 'docx', 'txt'].includes(extension)) {
          fileType = 'courseware';
        } else if (['jpg', 'jpeg', 'png', 'gif', 'pdf'].includes(extension)) {
          fileType = 'picturebook';
        }
      }

      const mergeResult = await childEnglishApi.mergeChunks({
        fileMd5: uploadTask.md5,
        fileName: file.name,
        totalChunks: totalChunks,
        uploadUser: uploadUser,
        fileType: fileType
      });

      uploadTask.status = 'completed';
      uploadTask.progress = 100;

      if (onSuccess) {
        onSuccess(mergeResult);
      }

      return mergeResult;

    } catch (error) {
      console.error('大文件上传失败:', error);
      uploadTask.status = 'error';

      if (onError) {
        onError(error);
      }

      throw error;
    } finally {
      // 清理上传队列
      this.uploadQueue.delete(fileId);
    }
  }

  /**
   * 上传分片
   */
  async uploadChunks(uploadTask, options) {
    const {
      onChunkProgress,
      onChunkComplete,
      onProgress,
      maxRetries = 3
    } = options;

    const promises = [];

    for (let chunkNumber = 1; chunkNumber <= uploadTask.totalChunks; chunkNumber++) {
      // 如果分片已上传完成，跳过
      if (uploadTask.chunks[chunkNumber] === 'completed') {
        continue;
      }

      // 控制并发数量
      if (promises.length >= this.maxConcurrentUploads) {
        await Promise.race(promises);
        // 移除已完成的Promise
        promises.splice(0, promises.length);
      }

      const promise = this.uploadChunkWithRetry(uploadTask, chunkNumber, {
        onChunkProgress,
        onChunkComplete,
        maxRetries
      });

      promises.push(promise);
    }

    // 等待所有分片上传完成
    await Promise.all(promises);
  }

  /**
   * 带重试机制的分片上传
   */
  async uploadChunkWithRetry(uploadTask, chunkNumber, options) {
    const { onChunkProgress, onChunkComplete, maxRetries } = options;

    let retryCount = 0;

    while (retryCount <= maxRetries) {
      try {
        await this.uploadSingleChunk(uploadTask, chunkNumber, {
          onChunkProgress: (progress) => {
            if (onChunkProgress) {
              onChunkProgress(chunkNumber, progress);
            }
          }
        });

        // 分片上传成功
        uploadTask.chunks[chunkNumber] = 'completed';
        uploadTask.uploadedChunks++;

        // 更新整体进度
        const overallProgress = (uploadTask.uploadedChunks / uploadTask.totalChunks) * 100;
        uploadTask.progress = overallProgress;

        if (onChunkComplete) {
          onChunkComplete(chunkNumber);
        }

        return;

      } catch (error) {
        retryCount++;

        if (retryCount > maxRetries) {
          console.error(`分片 ${chunkNumber} 上传失败，已达最大重试次数`);
          throw error;
        }

        console.warn(`分片 ${chunkNumber} 上传失败，第 ${retryCount} 次重试`);
        await this.delay(1000 * retryCount); // 指数退避
      }
    }
  }

  /**
   * 上传单个分片
   */
  async uploadSingleChunk(uploadTask, chunkNumber, options) {
    const { onChunkProgress } = options;

    const start = (chunkNumber - 1) * uploadTask.chunkSize;
    const end = Math.min(start + uploadTask.chunkSize, uploadTask.file.size);
    const chunkBlob = uploadTask.file.slice(start, end);

    const chunkData = {
      fileMd5: uploadTask.md5,
      fileName: uploadTask.file.name,
      chunkNumber: chunkNumber,
      totalChunks: uploadTask.totalChunks,
      chunkSize: uploadTask.chunkSize,
      fileSize: uploadTask.file.size
    };

    return await childEnglishApi.uploadChunk(
      chunkData,
      chunkBlob,
      onChunkProgress
    );
  }

  /**
   * 文件下载
   */
  async downloadFile(fileName, options = {}) {
    const {
      onProgress = null,
      onSuccess = null,
      onError = null,
      range = null
    } = options;

    try {
      const response = await childEnglishApi.downloadFile(fileName, range, onProgress);

      if (onSuccess) {
        onSuccess(response);
      }

      return response;
    } catch (error) {
      console.error('文件下载失败:', error);

      if (onError) {
        onError(error);
      }

      throw error;
    }
  }

  /**
   * 大文件断点续传下载
   */
  async downloadLargeFile(fileName, options = {}) {
    const {
      chunkSize = 5 * 1024 * 1024, // 5MB
      onProgress = null,
      onChunkProgress = null,
      onSuccess = null,
      onError = null,
      maxRetries = 3
    } = options;

    const downloadId = this.generateDownloadId(fileName);

    try {
      // 1. 获取文件信息
      console.log('获取文件下载信息:', fileName);
      const fileInfo = await childEnglishApi.getDownloadInfo(fileName);
      console.log('文件信息:', fileInfo);
      
      const totalSize = fileInfo.fileSize;
      console.log('文件大小:', totalSize, 'bytes, 分片大小:', chunkSize, 'bytes');
      
      // 如果文件很小，直接使用简单下载
      if (totalSize < chunkSize) {
        console.log('文件较小，使用简单下载');
        const response = await childEnglishApi.downloadFile(fileName, null, onProgress);
        const blob = response.data instanceof Blob ? response.data : response;
        
        if (!blob || blob.size === 0) {
          throw new Error('下载的文件为空');
        }
        
        if (onSuccess) {
          onSuccess(blob, fileInfo);
        }
        
        return blob;
      }
      
      const totalChunks = Math.ceil(totalSize / chunkSize);
      console.log('总分片数:', totalChunks);

      // 2. 检查本地下载进度
      const savedProgress = this.getDownloadProgress(downloadId);
      let startChunk = savedProgress ? savedProgress.currentChunk : 1;
      let downloadedSize = savedProgress ? savedProgress.downloadedSize : 0;

      const chunks = [];
      const downloadPromises = [];

      // 3. 分片下载
      for (let chunkNumber = startChunk; chunkNumber <= totalChunks; chunkNumber++) {
        const start = (chunkNumber - 1) * chunkSize;
        const end = Math.min(start + chunkSize, totalSize) - 1;
        const range = `bytes=${start}-${end}`;

        // 控制并发数量
        if (downloadPromises.length >= this.maxConcurrentDownloads) {
          await Promise.race(downloadPromises);
        }

        const promise = this.downloadChunkWithRetry(
          fileName,
          chunkNumber,
          range,
          {
            onChunkProgress: (progress, chunkSize) => {
              if (onChunkProgress) {
                onChunkProgress(chunkNumber, progress, chunkSize);
              }

              // 更新整体进度
              const overallProgress = ((downloadedSize + (progress / 100) * chunkSize) / totalSize) * 100;
              if (onProgress) {
                onProgress(overallProgress);
              }
            },
            maxRetries
          }
        ).then(chunkData => {
          chunks[chunkNumber - 1] = chunkData;
          downloadedSize += chunkData.size;

          // 保存下载进度
          this.saveDownloadProgress(downloadId, {
            currentChunk: chunkNumber + 1,
            downloadedSize: downloadedSize,
            totalSize: totalSize
          });
        });

        downloadPromises.push(promise);
      }

      await Promise.all(downloadPromises);

      console.log('所有分片下载完成，分片数量:', chunks.length, '分片详情:', chunks.map(c => ({
        chunkNumber: c?.chunkNumber,
        size: c?.size,
        hasData: !!c?.data,
        dataSize: c?.data?.size || 0
      })));

      // 4. 合并分片
      const mergedBlob = this.mergeChunks(chunks);
      console.log('合并后的Blob大小:', mergedBlob?.size || 0, 'bytes');

      if (!mergedBlob || mergedBlob.size === 0) {
        console.error('合并后的Blob为空！分片详情:', chunks);
        throw new Error('下载的文件为空');
      }

      // 5. 清理下载记录
      this.clearDownloadProgress(downloadId);

      if (onSuccess) {
        onSuccess(mergedBlob, fileInfo);
      }

      return mergedBlob;

    } catch (error) {
      console.error('大文件下载失败:', error);

      if (onError) {
        onError(error);
      }

      throw error;
    }
  }

  /**
   * 下载分片（带重试）
   */
  async downloadChunkWithRetry(fileName, chunkNumber, range, options) {
    const { onChunkProgress, maxRetries } = options;

    let retryCount = 0;

    while (retryCount <= maxRetries) {
      try {
        const response = await childEnglishApi.downloadFile(fileName, range, onChunkProgress);
        console.log(`分片 ${chunkNumber} 下载响应:`, {
          responseType: typeof response,
          hasData: !!response.data,
          dataType: typeof response.data,
          dataSize: response.data?.size || 0,
          headers: response.headers
        });
        
        // response 可能是完整的 response 对象（如果拦截器返回了 response）
        // 或者直接是 response.data（如果拦截器返回了 response.data）
        const blob = response.data instanceof Blob ? response.data : 
                    (response instanceof Blob ? response : null);
        const headers = response.headers || {};
        const size = blob ? blob.size : parseInt(headers['content-length'] || '0');
        
        if (!blob || blob.size === 0) {
          console.error(`分片 ${chunkNumber} 数据为空:`, { blob, size, headers });
          throw new Error(`分片 ${chunkNumber} 数据为空`);
        }
        
        return {
          data: blob,
          size: size,
          chunkNumber: chunkNumber
        };
      } catch (error) {
        retryCount++;

        if (retryCount > maxRetries) {
          throw new Error(`分片 ${chunkNumber} 下载失败: ${error.message}`);
        }

        console.warn(`分片 ${chunkNumber} 下载失败，第 ${retryCount} 次重试`);
        await this.delay(1000 * retryCount);
      }
    }
  }

  /**
   * 合并分片数据
   */
  mergeChunks(chunks) {
    console.log('开始合并分片，原始分片数量:', chunks.length);
    
    // 过滤掉空的分片
    const validChunks = chunks.filter(chunk => chunk && chunk.data);
    console.log('有效分片数量:', validChunks.length);
    
    if (validChunks.length === 0) {
      console.error('没有有效的分片数据！');
      return new Blob([]);
    }
    
    // 按分片顺序排序
    const sortedChunks = validChunks.sort((a, b) => a.chunkNumber - b.chunkNumber);
    console.log('排序后的分片:', sortedChunks.map(c => ({
      chunkNumber: c.chunkNumber,
      size: c.size,
      dataSize: c.data?.size || 0
    })));

    // 创建Blob数组
    const blobArrays = sortedChunks.map(chunk => {
      if (!chunk.data || chunk.data.size === 0) {
        console.warn('分片数据为空:', chunk.chunkNumber);
      }
      return chunk.data;
    });

    // 合并Blob
    const mergedBlob = new Blob(blobArrays);
    console.log('合并完成，最终Blob大小:', mergedBlob.size, 'bytes');
    
    return mergedBlob;
  }

  /**
   * 获取文件列表
   */
  async getFileList(params = {}) {
    try {
      const response = await childEnglishApi.getFileList(params);
      return response;
    } catch (error) {
      console.error('获取文件列表失败:', error);
      throw error;
    }
  }

  /**
   * 获取文件信息
   */
  async getFileInfo(fileName) {
    try {
      const response = await childEnglishApi.getFileInfo(fileName);
      return response;
    } catch (error) {
      console.error('获取文件信息失败:', error);
      throw error;
    }
  }

  /**
   * 删除文件
   */
  async deleteFile(fileName) {
    try {
      const response = await childEnglishApi.deleteFile(fileName);
      return response;
    } catch (error) {
      console.error('删除文件失败:', error);
      throw error;
    }
  }

  /**
   * 暂停上传
   */
  pauseUpload(fileId) {
    const uploadTask = this.uploadQueue.get(fileId);
    if (uploadTask) {
      uploadTask.status = 'paused';
    }
  }

  /**
   * 恢复上传
   */
  resumeUpload(fileId) {
    const uploadTask = this.uploadQueue.get(fileId);
    if (uploadTask) {
      uploadTask.status = 'uploading';
    }
  }

  /**
   * 取消上传
   */
  cancelUpload(fileId) {
    const uploadTask = this.uploadQueue.get(fileId);
    if (uploadTask) {
      uploadTask.status = 'cancelled';
      // 清理服务器上的临时分片
      if (uploadTask.md5) {
        childEnglishApi.cleanupChunks(uploadTask.md5).catch(console.error);
      }
    }
    this.uploadQueue.delete(fileId);
  }

  /**
   * 计算文件MD5（抽样计算，适用于大文件）
   */
  async calculateFileMD5(file, sampleSize = 1024 * 1024) {
    // 对大文件进行抽样计算
    if (file.size > sampleSize * 2) {
      // 取文件头、中间、尾部的样本
      const samples = [
        file.slice(0, sampleSize),
        file.slice(file.size / 2 - sampleSize / 2, file.size / 2 + sampleSize / 2),
        file.slice(file.size - sampleSize, file.size)
      ];

      const sampleBlob = new Blob(samples);
      return await this.calculateBlobMD5(sampleBlob);
    } else {
      return await this.calculateBlobMD5(file);
    }
  }

  /**
   * 计算Blob的MD5
   */
  calculateBlobMD5(blob) {
    return new Promise((resolve, reject) => {
      const reader = new FileReader();

      reader.onload = () => {
        const buffer = reader.result;
        const wordArray = this.arrayBufferToWordArray(buffer);
        const md5 = CryptoJS.MD5(wordArray).toString();
        resolve(md5);
      };

      reader.onerror = reject;
      reader.readAsArrayBuffer(blob);
    });
  }

  /**
   * ArrayBuffer转WordArray（CryptoJS格式）
   */
  arrayBufferToWordArray(arrayBuffer) {
    const u8 = new Uint8Array(arrayBuffer);
    const len = u8.length;
    const words = [];

    for (let i = 0; i < len; i++) {
      words[i >>> 2] |= (u8[i] & 0xff) << (24 - (i % 4) * 8);
    }

    return CryptoJS.lib.WordArray.create(words, len);
  }

  /**
   * 保存下载进度到本地存储
   */
  saveDownloadProgress(downloadId, progress) {
    try {
      localStorage.setItem(`download_${downloadId}`, JSON.stringify(progress));
    } catch (error) {
      console.warn('保存下载进度失败:', error);
    }
  }

  /**
   * 获取下载进度
   */
  getDownloadProgress(downloadId) {
    try {
      const progress = localStorage.getItem(`download_${downloadId}`);
      return progress ? JSON.parse(progress) : null;
    } catch (error) {
      console.warn('获取下载进度失败:', error);
      return null;
    }
  }

  /**
   * 清理下载进度
   */
  clearDownloadProgress(downloadId) {
    try {
      localStorage.removeItem(`download_${downloadId}`);
    } catch (error) {
      console.warn('清理下载进度失败:', error);
    }
  }

  /**
   * 生成文件ID
   */
  generateFileId(file) {
    return `file_${file.name}_${file.size}_${file.lastModified}`;
  }

  /**
   * 生成下载ID
   */
  generateDownloadId(fileName) {
    return `download_${fileName}_${Date.now()}`;
  }

  /**
   * 延迟函数
   */
  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }

  /**
   * 获取上传队列
   */
  getUploadQueue() {
    return Array.from(this.uploadQueue.values());
  }

  /**
   * 获取下载队列
   */
  getDownloadQueue() {
    return Array.from(this.downloadQueue.values());
  }

  /**
   * 设置最大并发数
   */
  setMaxConcurrentUploads(max) {
    this.maxConcurrentUploads = Math.max(1, max);
  }

  setMaxConcurrentDownloads(max) {
    this.maxConcurrentDownloads = Math.max(1, max);
  }
}

// 创建单例实例
export const fileService = new FileService();
